package top.hmtools.controllers;

import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;

import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Accordion;
import javafx.scene.control.Button;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.control.TitledPane;
import javafx.scene.control.TreeCell;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.control.cell.TextFieldTreeCell;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import javafx.util.Callback;
import top.hmtools.base.StringTools;
import top.hmtools.base.ValidationTools;
import top.hmtools.beans.MapperXmlSqlPartGroupBean;
import top.hmtools.beans.MapperXmlSqlPartTempletBean;
import top.hmtools.callBacks.SqlPartTempletListCallBack;
import top.hmtools.commons.AlertUtil;
import top.hmtools.enums.EDBType;
import top.hmtools.enums.ESqlPartFactor;
import top.hmtools.model.ResultModel;
import top.hmtools.random.RandomStringTools;
import javafx.scene.control.ComboBox;

public class SqlPartMainPaneController extends BaseController{
	@FXML
	private AnchorPane LeftAnchorPane;
	@FXML
	private Accordion accordionSqlParts;
	@FXML
	private AnchorPane RightAnchorPane;
	@FXML
	private Button btn_refresh;
	@FXML
	private Button btn_del;
	@FXML
	private Button btn_reset;
	@FXML
	private Button btn_update;
	@FXML
	private Button btn_add;
	@FXML
	private TextField tf_sqlPartName;
	@FXML
	private TextField tf_factorName;
	@FXML
	private TextField tf_daoMethodName;
	@FXML
	private TextArea ta_content;
	@FXML
	private TextArea ta_comment;
	@FXML
	private ChoiceBox<String> cb_groupId;
	@FXML
	private ChoiceBox<String> cb_dataType;
	@FXML
	private TextField tf_id;
	@FXML
	ComboBox<String> cb_factors;
	@FXML
	Button btn_insertFactor;
	
	//SQL片段编辑框中光标位置
	protected int caretPosition;
	

	// Event Listener on Button[#btn_refresh].onAction
	@FXML
	public void doRefresh(ActionEvent event) {
	    this.initDataType();
	    this.initSqlGroup();
	    this.initSqlPartTempletTree();
	}
	// Event Listener on Button[#btn_del].onAction
	@FXML
	public void doDel(ActionEvent event) {
	    String id = this.tf_id.getText();
        if(StringTools.isBlank(id)){
            AlertUtil.showWarnAlert("请选择一条数据");
            return;
        }
        ResultModel result = this.sqlPartManageService.delSqlPartTempletById(id);
        
        initSqlPartTempletTree();
        int dbTypecode = EDBType.getTypeCodeByName(String.valueOf(this.cb_dataType.getValue()));
        this.ExpandedPane(EDBType.getByTypeCode(dbTypecode));
        if(result.isStatusSuccess()){
            AlertUtil.showInfoAlert(result.getMessage());
        }else{
            AlertUtil.showErrorAlert(result.getMessage());
        }
	}
	// Event Listener on Button[#btn_reset].onAction
	@FXML
	public void doReset(ActionEvent event) {
	    this.tf_daoMethodName.setText(null);
	    this.tf_factorName.setText(null);
	    this.tf_sqlPartName.setText(null);
	    
	    this.ta_comment.setText(null);
	    this.ta_content.setText(null);

	    this.cb_dataType.getSelectionModel().selectFirst();
	    this.cb_groupId.getSelectionModel().selectFirst();
	}
	// Event Listener on Button[#btn_update].onAction
	@FXML
	public void doUpdate(ActionEvent event) {
	    String id = this.tf_id.getText();
	    if(StringTools.isBlank(id)){
	        AlertUtil.showWarnAlert("请选择一条数据");
	        return;
	    }
	    boolean validationInput = this.validationInput();
        if(!validationInput){
            return;
        }
        MapperXmlSqlPartTempletBean bean = new MapperXmlSqlPartTempletBean();
        bean.setComment(this.ta_comment.getText());
        bean.setContent(this.ta_content.getText());
        int dbTypecode = EDBType.getTypeCodeByName(String.valueOf(this.cb_dataType.getValue()));
        bean.setDb_type(dbTypecode);
        bean.setFactor_name(this.tf_factorName.getText());
       
        int selectedIndex = this.cb_groupId.getSelectionModel().getSelectedIndex();
        List<MapperXmlSqlPartGroupBean> groups = (List<MapperXmlSqlPartGroupBean>)this.cb_groupId.getUserData();
        String groupId = groups.get(selectedIndex).getId();
        bean.setGroup_id(groupId);
        
        bean.setId(this.tf_id.getText());
        bean.setMethod_name(this.tf_daoMethodName.getText());
        bean.setName(this.tf_sqlPartName.getText());
        ResultModel result = this.sqlPartManageService.updateSqlPartTemplet(bean);
        
        initSqlPartTempletTree();
        this.ExpandedPane(EDBType.getByTypeCode(dbTypecode));
        if(result.isStatusSuccess()){
            AlertUtil.showInfoAlert(result.getMessage());
        }else{
            AlertUtil.showErrorAlert(result.getMessage());
        }
	}
	
	/**
	 * 新增
	* 方法说明：                    doAdd
	* 输入参数说明：           @param event
	* 输出参数说明：           void
	*
	*
	 */
	@FXML
	public void doAdd(ActionEvent event) {
	    boolean validationInput = this.validationInput();
	    if(!validationInput){
	        return;
	    }
	    MapperXmlSqlPartTempletBean bean = new MapperXmlSqlPartTempletBean();
	    bean.setComment(this.ta_comment.getText());
	    bean.setContent(this.ta_content.getText());
	    int dbTypecode = EDBType.getTypeCodeByName(String.valueOf(this.cb_dataType.getValue()));
	    bean.setDb_type(dbTypecode);
	    bean.setFactor_name(this.tf_factorName.getText());
	    
	    int selectedIndex = this.cb_groupId.getSelectionModel().getSelectedIndex();
	    List<MapperXmlSqlPartGroupBean> groups = (List<MapperXmlSqlPartGroupBean>)this.cb_groupId.getUserData();
	    String groupId = groups.get(selectedIndex).getId();
	    bean.setGroup_id(groupId);
	    
	    bean.setId(RandomStringTools.getYyyyMMddHHmmssSSSPrifixInteger(6));
	    bean.setMethod_name(this.tf_daoMethodName.getText());
	    bean.setName(this.tf_sqlPartName.getText());
	    ResultModel result = this.sqlPartManageService.addSqlPartTemplet(bean);
	    
	    initSqlPartTempletTree();//刷新折叠面板
	    this.ExpandedPane(EDBType.getByTypeCode(dbTypecode));
	    if(result.isStatusSuccess()){
	        AlertUtil.showInfoAlert(result.getMessage());
	    }else{
	        AlertUtil.showErrorAlert(result.getMessage());
	    }
	}
	
	/**
	 * 展开指定的折叠面板
	* 方法说明：                    ExpandedPane
	* 输入参数说明：           @param edbType
	* 输出参数说明：           void
	*
	*
	 */
	private void ExpandedPane(EDBType edbType){
	    ObservableList<TitledPane> panes = this.accordionSqlParts.getPanes();
	    for(TitledPane item:panes){
	        String text = item.getText();
	        if(edbType.getName().equals(text)){
	            item.setExpanded(true);
	        }
	    }
	}
	
	/**
	 * 验证输入框的值
	* 方法说明：                    validationInput
	* 输入参数说明：           @return
	* 输出参数说明：           boolean
	*
	*
	 */
	private boolean validationInput(){
	    String methodName = this.tf_daoMethodName.getText();
	    if(StringTools.isBlank(methodName)){
	        AlertUtil.showWarnAlert("方法名称不能为空");
	        return false;
	    }
	    String factorName = this.tf_factorName.getText();
	    if(StringTools.isBlank(factorName)){
	        AlertUtil.showWarnAlert("因子名称不能为空");
	        return false;
	    }
	    boolean isRightfulString = ValidationTools.isRightfulString(factorName);
	    if(!isRightfulString){
	        AlertUtil.showWarnAlert("因子名称只能为英文字母及数字");
            return false;
	    }
	    String sqlPartName = this.tf_sqlPartName.getText();
	    if(StringTools.isBlank(sqlPartName)){
	        AlertUtil.showWarnAlert("片段名称不能为空");
	        return false;
	    }
	    String content = this.ta_content.getText();
	    if(StringTools.isBlank(content)){
	        AlertUtil.showWarnAlert("片段语句内容不能为空");
            return false;
	    }
	    return true;
	}
    /**
     * 方法说明
     * 输入参数说明
     * 输出参数说明
     */
    @Override
    public void initialize(URL location, ResourceBundle resources) {
        //初始化数据库类型
        initDataType();
        
        //初始化组别
        initSqlGroup();
        
        //初始化左边分类框
        this.initSqlPartTempletTree();
        
        this.initFactors();
        
        //设置SQL模板文件内容文本域失去焦点时获取光标的位置
	    this.ta_content.focusedProperty().addListener(new InvalidationListener() {
			@Override
			public void invalidated(Observable observable) {
				caretPosition = ta_content.getCaretPosition();
			}
		});
    }
    
    /**
     * 初始化sql语句片段名称树
    * 方法说明：                    initSqlPartTempletTree
    * 输入参数说明：           
    * 输出参数说明：           void
    *
    *
     */
    private void initSqlPartTempletTree(){
        //清空面板数据
        this.accordionSqlParts.getPanes().clear();
        
        //遍历数据库类别
        for(EDBType item:EDBType.values()){
            //获取类别名称及内容数据，并初始化 TitledPane 折叠面板
            String name = item.getName();
            TreeView< String> treeView = new TreeView<>();
            treeView.setRoot(new TreeItem<>());
            treeView.setShowRoot(false);
            
            Callback<TreeView<String>, TreeCell<String>> defaultCellFactory =  TextFieldTreeCell.forTreeView();
            treeView.setCellFactory(new SqlPartTempletListCallBack(defaultCellFactory,this.tf_daoMethodName,this.tf_factorName,this.tf_id,this.tf_sqlPartName,this.cb_dataType,this.cb_groupId,this.ta_comment,this.ta_content));
            
            ResultModel resultModel = this.sqlPartManageService.getSqlPartTempletsByDataType(item.getTypeCode());
            if(resultModel.isStatusSuccess()){
                List<MapperXmlSqlPartTempletBean> rows = resultModel.getRows();
                for(int ii=0;rows != null && ii<rows.size();ii++){
                    MapperXmlSqlPartTempletBean bean = rows.get(ii);
                    TreeItem<String> tItem = new TreeItem<String>();
                    tItem.setValue(StringTools.isBlank(bean.getGroup_id())?"":"("+bean.getGroupName()+")"+bean.getName());
                    ImageView icon = new ImageView("images/file.png");
                    icon.setFitHeight(16);
                    icon.setFitWidth(16);
                    icon.setUserData(bean);
                    tItem.setGraphic(icon);
                    tItem.setGraphic(icon);
                    
                    treeView.getRoot().getChildren().add(tItem);
                }
            }
            
            TitledPane titledPane = new TitledPane(name,treeView);
            this.accordionSqlParts.getPanes().add(titledPane);
        }
    }
    
    /**
     * 初始化数据片段分组下拉框
    * 方法说明：                    initSqlGroup
    * 输入参数说明：           
    * 输出参数说明：           void
    *
    *
     */
    private void initSqlGroup(){
        this.cb_groupId.getItems().clear();
        ObservableList<String> groups = FXCollections.observableArrayList();
        ResultModel allSqlPartGroup = this.sqlPartManageService.getAllSqlPartGroup();
        if(allSqlPartGroup.isStatusSuccess()){
            List<MapperXmlSqlPartGroupBean> rows = allSqlPartGroup.getRows();
            for(int ii=0;ii<rows.size();ii++){
                MapperXmlSqlPartGroupBean mapperXmlSqlPartGroupBean = rows.get(ii);
                String name = mapperXmlSqlPartGroupBean.getName();
                groups.add(ii,name);
                if(ii==0){
                    this.cb_groupId.setValue(name);
                }
            }
            this.cb_groupId.setUserData(rows);
        }
        this.cb_groupId.setItems(groups);
    }
    
    /**
     * 初始化数据库类型下拉框
    * 方法说明：                    initDataType
    * 输入参数说明：           
    * 输出参数说明：           void
    *
    *
     */
    private void initDataType(){
        this.cb_dataType.getItems().clear();
        ObservableList<String> dbTypes = FXCollections.observableArrayList();
        int index = 0;
        for(EDBType item:EDBType.values()){
            String name = item.getName();
            dbTypes.add(name);
            if(index==0){
                this.cb_dataType.setValue(name);
            }
            index++;
        }
        this.cb_dataType.setItems(dbTypes);
    }
    
    /**
     * 初始化因子下拉框
     */
    private void initFactors(){
    	ObservableList<String> items = this.cb_factors.getItems();
    	int index = 0;
    	List<ESqlPartFactor> factorList = new ArrayList<>();
    	for(ESqlPartFactor factor:ESqlPartFactor.values()){
    		String value = factor.getComment();
    		items.add(index,value);
    		factorList.add(index,factor);
    		if(index==0){
    			this.cb_factors.setValue(value);
    		}
    		index++;
    	}
    	this.cb_factors.setItems(items);
    	this.cb_factors.setUserData(factorList);
    }

    /**
     * 插入因子到SQL片段编辑文本域
     * @param event
     */
	@FXML
	public void doInsertFactor(ActionEvent event) {
		int index = this.cb_factors.getSelectionModel().getSelectedIndex();
		if(index<0){
			return;
		}
		List<ESqlPartFactor> factorList = (List<ESqlPartFactor>) this.cb_factors.getUserData();
		ESqlPartFactor sqlPartFactor = factorList.get(index);
		String factor = "${"+sqlPartFactor.toString()+"!}";
		this.ta_content.insertText(caretPosition, factor);
	}
}
